package com.glc.hms.core.aop;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.glc.hms.common.util.HttpUtil;
import com.glc.hms.core.annotation.SysLogAnno;
import com.glc.hms.core.common.log.LogManager;
import com.glc.hms.core.common.log.LogTaskFactory;
import com.glc.hms.core.shiro.ShiroUtil;
import com.glc.hms.system.entity.SysLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**
 * 系统日志，切面处理类
 * Created by Chenhz on 2019/11/22.
 *
 */
@Aspect
@Component
@Order(200)
public class LogAop {


    @Pointcut("@annotation(com.glc.hms.core.annotation.SysLogAnno)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //保存日志
        saveSysLog(point, time);
        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SysLog log = new SysLog();
        SysLogAnno sysLogAnno = method.getAnnotation(SysLogAnno.class);
        if(sysLogAnno == null){
            throw new IllegalArgumentException("该注解需要指定参数");
        }
        //注解上的描述
        String value = sysLogAnno.value();
        Integer type = sysLogAnno.type();

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.setMethod(className + "." + methodName + "()");

        //请求的参数
        String sb = getArgsNameAndValue(joinPoint);

        //用户名
        String principal = ShiroUtil.getUserNotNull().getUsername();

        //登陆日志
        if(type==1){
            LogManager.me().executeLog(LogTaskFactory.loginLog(principal,value,sb.toString(),className + "." + methodName + "()",time, HttpUtil.getIp()));
        }
        //操作日志
        else {
            LogManager.me().executeLog(LogTaskFactory.buinessLog(principal,value,sb.toString(),className + "." + methodName + "()",time, HttpUtil.getIp()));
        }
    }


    /**
     * 获取切面方法的参数名称和参数值
     *
     * @param joinPoint
     * @return param1=value1,param2=value2,param3=value3
     */
    private String getArgsNameAndValue(JoinPoint joinPoint) {
        StringBuilder sb = new StringBuilder();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        String[] parameterNames = methodSignature.getParameterNames();
        Object[] args = joinPoint.getArgs();
        if (!ArrayUtils.isEmpty(parameterNames)) {
            for (int i = 0; i < parameterNames.length; i++) {
                Object arg = args[i];
                if (arg instanceof ServletRequest || arg instanceof ServletResponse || arg instanceof HttpSession) {
                    continue;
                }
                String argJson = JSON.toJSONString(arg);
                sb.append(parameterNames[i] + "=" + argJson).append(",");
            }
        }
        int lastIndex = sb.lastIndexOf(",");
        if (lastIndex > 0) {
            sb.deleteCharAt(sb.lastIndexOf(","));
        }

        return sb.toString();
    }
}

